package com.yonyou.wdt.job;


import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yonyou.wdt.entity.OpenApiURLEnum;
import com.yonyou.wdt.entity.QueryDto;
import com.yonyou.wdt.job.config.BaseConfig;
import com.yonyou.wdt.service.YonsuiteService;
import com.yonyou.wdt.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName YsPurOrderToWdtJob
 * @Description YS调拨出库单同步旺店通委外订单单
 * @Author HuangWb
 * @Date 2024/4/26 17:08
 */
@Component
public class YsAllocationOutToWdtOutsourcingJob extends BaseConfig {


    private static final Logger logger = LoggerFactory.getLogger(YsAllocationOutToWdtOutsourcingJob.class);
    private final WdtConfigProperties configProperties;
    @Autowired
    public YsAllocationOutToWdtOutsourcingJob(WdtConfigProperties configProperties) {
        this.configProperties = configProperties;
    }
    @Resource
    private YonsuiteService yonsuiteService;
    private static final String JOB_CLASS="longPai001";
    /**
     * @Author Huangwb
     * @Description YS调拨出库单同步旺店通委外订单单
     * @Date 2024/4/26 17:41
     **/
    @XxlJob("ysAllocationOutToWdtOutsourcingJob")
    public ReturnT<String> YsAllocationOutToWdtOutsourcingJob() {
        String param = XxlJobHelper.getJobParam();
        Map<String, Object> map = new HashMap<>();
        if (param != null && !param.isEmpty()) {
            List<String> timeRange = Arrays.asList(param.split("\\|"));
            if (timeRange.size() == 2) {
                map.put("Start", timeRange.get(0));
                map.put("End", timeRange.get(1));
            } else {
                // 单据编码
                map.put("code", param);
            }
        } else {
            map.put("Start", DateUtils.getStartDateBy10m());
            map.put("End", DateUtils.getEndDateBy10m());
        }
        // 处理相关业务
        QueryDto dto = new QueryDto();
        dto.setTenantId(getYsTenantId());
        dto.setAppKey(getYsAppKey());
        dto.setAppSecret(getYsAppSecret());
        // 获取YS系统租户动态域名信息
        ReturnT<String> isReturn2 = getYsDynamicDomainName(JOB_CLASS,dto);
        // 域名获取失败
        if (isReturn2 != null) return isReturn2;
        try {

            ArrayList<JSONObject> ysPurchaseRecord = getYsTransferOut(map, dto);
            if (!ysPurchaseRecord.isEmpty()) {
                // 查询YS仓库档案列表
                HashMap<String, String> ckData = YsQueryUtil.getCkData(dto,yonsuiteService);
                int index = 1;
                logger.info("当前时间段：{}至{}委外入库数据有：{}条", map.get("Start"), map.get("End"), ysPurchaseRecord.size());
                Map<String, List<JSONObject>> groupByIdMap = groupById(ysPurchaseRecord);
                for (Map.Entry<String, List<JSONObject>> idKey : groupByIdMap.entrySet()) {
                    List<JSONObject> value = idKey.getValue();
                    // 单据号
                    String ysCode = value.get(0).getStr("code");
                    // 解析数据，组装旺店通请求数据,调用旺店通接口保存数据
                    try {
                        JSONObject response = assembleRequest(value,ckData,dto);
                        if (response != null) {
                            if (null != response && response.getInt("code") == 0) {
                                logger.info("YS调拨出库：{} 同步旺店通委外订单成功", ysCode);
                                InsertLogger(JOB_CLASS,ysCode, "1", "YS调拨出库："+ysCode+"同步旺店通委外订单"+response.getJSONObject("data").getStr("stockout_no")+"成功。");
                            } else {
                                InsertLogger(JOB_CLASS,ysCode, "0", "YS调拨出库：{"+ysCode+"}同步旺店通委外订单"+response.getStr("message")+"成功。");
                            }
                        } else {
                            logger.error("YS调拨出库单：{}，同步旺店委外入库失败",ysCode);
                            InsertLogger(JOB_CLASS,ysCode, "0", "YS调拨出库：{"+ysCode+"}同步旺店通委外订单失败：联系开发解决。");
                        }
                        // 旺店通接口频率问题处理
                        this.APICurrentLimiting("stockout_order_push.php",60);
                    } catch (Exception e) {
                        logger.error("YS调拨出库：{}同步旺店通失败：{}", ysCode, e.getMessage());
                        InsertLogger(JOB_CLASS,ysCode, "0", "YS调拨出库：{"+ysCode+"}同步旺店通委外订单失败。");
                    }
                    // 旺店通接口频率问题处理
                    this.APICurrentLimiting("purchase_return_push.php",59);
                }
            }
        } catch (Exception e) {
            logger.error("Error occurred", e);
            logger.error("YS调拨出库同步旺店通委外订单失败：" + e.getMessage());
            return ReturnT.FAIL;
        }
        logger.info("  --  YS调拨出库同步旺店通委外订单任务执行完成  --  ");
        return ReturnT.SUCCESS;
    }

    /**
     * @return
     * @Author Huangwb
     * @Description 组装旺店通接口请求查询并调用旺店通接口保存数据
     * @Date 10:48 2023/5/23
     * @Param
     **/
    private JSONObject assembleRequest(List<JSONObject> ckJsonObject,HashMap<String, String> ckData,QueryDto dto) {
        // 旺店通委外订单新建请求
        // 单据号
        JSONObject ysData = ckJsonObject.get(0);
        String ysCode = ysData.getStr("code");
        HashMap<String, Object> otherInfoMap = new HashMap<>();
        // 仓库编码
        String warehouse = ckData.get(ysData.getStr("inwarehouse"));
        otherInfoMap.put("warehouse_no",warehouse);
        otherInfoMap.put("api_outer_no",ysCode);
        otherInfoMap.put("order_type",2);//可选值：1(出库)；2（入库）
        otherInfoMap.put("remark",ysData.getStr("memo"));//可选值：1(出库)；2（入库）
        ArrayList<Map<String, Object>> detailsList = new ArrayList<>();
        for (JSONObject entries : ckJsonObject) {
            HashMap<String, Object> detailsMap = new HashMap<>();
            String ysProCode =entries.getStr("product_cCode");
            // 获取Redis中物料档案信息
            JSONObject redisPrJson = (JSONObject) RedisUtils.get(dto.getTenantId() + ":product:" + ysProCode);
            if (redisPrJson == null) {
                // 保存同步错误日志，未找到对应物料档案信息
                logger.error("存在未同步YS系统物料数据：{}，请同步后重试", ysProCode);
                InsertLogger(JOB_CLASS,ysCode, "0", "存在未同步YS系统物料数据："+ysProCode+"，请同步后重试");
                return null;
            }
            detailsMap.put("spec_no",redisPrJson.getStr("erpCode"));
            detailsMap.put("num",entries.getBigDecimal("subQty"));
            detailsMap.put("price",entries.getBigDecimal("natUnitPrice"));
            detailsList.add(detailsMap);
        }
        otherInfoMap.put("goods_list",detailsList);
        HashMap<String, Object> purchaseMap = new HashMap<>();
        purchaseMap.put("stockin_info",JSONUtil.toJsonStr(otherInfoMap));

        WdtClient client = new WdtClient(configProperties.getSid(), configProperties.getKey(), configProperties.getSecret(), configProperties.getUrl());
        String res = null;
        try {
            res = client.execute("vip_wms_stockinout_order_push.php", purchaseMap);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return JSONUtil.parseObj(res);
    }

    /**
     * @return
     * @Author Huangwb
     * @Description YS调拨出库列表查询
     * @Date 10:39 2023/5/23
     * @Param
     **/
    private ArrayList<JSONObject> getYsTransferOut(Map<String, Object> map, QueryDto dto) throws Exception {
        HashMap<String, Object> purQueryMap = new HashMap<>();
        purQueryMap.put("pageSize", 100);
        // 单据状态
//		purQueryMap.put("status", "1");
        // 查询表头
        purQueryMap.put("isSum", false);
        ArrayList<Map<String, Object>> simpleVosList = new ArrayList<>();
        HashMap<String, Object> simpleVosMaps = new HashMap<>();
        if (null != map.get("Start")) {
            // 根据单据审核时间区间查询
            simpleVosMaps.put("field", "auditTime");
            simpleVosMaps.put("op", "between");
            simpleVosMaps.put("value1", map.get("Start"));
            simpleVosMaps.put("value2", map.get("End"));
        } else if (null != map.get("code")) {
            // 根据单据编码查询
            simpleVosMaps.put("field", "code");
            simpleVosMaps.put("op", "eq");
            simpleVosMaps.put("value1", map.get("code"));
        }
        // 根据交易类型查询
        HashMap<String, Object> statusMap = new HashMap<>();
        statusMap.put("field", "status");
        statusMap.put("op", "eq");
        statusMap.put("value1", 1);
        simpleVosList.add(simpleVosMaps);
        simpleVosList.add(statusMap);
      /*  HashMap<String, Object> typeMap = new HashMap<>();
        typeMap.put("field", "bustype");
        typeMap.put("op", "eq");
        typeMap.put("value1", "2134093710555086878");//委外入库—同步
        simpleVosList.add(typeMap);*/
        purQueryMap.put("simpleVOs", simpleVosList);
        int pageIndex = 1;
        ArrayList<JSONObject> purList = new ArrayList<>();
        int errorIndex = 0;
        while (true) {
            purQueryMap.put("pageIndex", pageIndex);
            JSONObject purJson = yonsuiteService.transferOutList(purQueryMap,dto);
            if ("200".equals(purJson.getStr("code"))) {
                if (null != purJson.getJSONObject("data") && null != purJson.getJSONObject("data").getJSONArray("recordList")) {
                    JSONArray purJsonArray = purJson.getJSONObject("data").getJSONArray("recordList");
                    for (Object pur : purJsonArray) {
                        purList.add((JSONObject) pur);
                    }
                }
                if (purJson.getJSONObject("data").getInt("recordCount") <= pageIndex * 100) {
                    break;
                }
                // 接口执行频率问题处理
               this.APICurrentLimiting(OpenApiURLEnum.OTHER_OUT_LIST_QUERY,59);
                pageIndex++;
            } else {
                if (errorIndex < 10) {
                    errorIndex++;
                    logger.error("查询YS调拨出库第：{}，页失败：{},延迟一秒查询", pageIndex, purJson.getOrDefault("message", "接口未返回数据"));
                    Thread.sleep(1000);
                } else {
                    // 多次失败， 退出定时任务排查原因
                    logger.error("定时任务多次执行失败，此次任务作废");
                    return new ArrayList<>();
                }
            }
        }
        return purList;
    }

    /**
     * @return
     * @Author Huangwb
     * @Description 根据单据id进行分组(主子表合并)
     * @Date 18:11 2023/5/11
     * @Param
     **/
    private Map<String, List<JSONObject>> groupById(ArrayList<JSONObject> ysPurinrecordList) {
        return ysPurinrecordList.stream().collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("id")));
    }
}
